package com.travel.server.manager.impl.command.project.data;

import com.travel.common.CommonConstant;
import com.travel.common.util.CollectionUtil;
import com.travel.common.util.CommonUtil;
import com.travel.common.util.DateUtil;
import com.travel.server.manager.dto.request.project.data.QueryProjectCostRequest;
import com.travel.server.manager.dto.request.project.data.QueryProjectProfitListRequest;
import com.travel.server.manager.dto.response.project.data.QueryProjectCostResponse;
import com.travel.server.manager.dto.response.project.data.QueryProjectCostResponse.CostItem;
import com.travel.server.manager.dto.response.project.data.QueryProjectProfitListResponse;
import com.travel.server.manager.dto.response.project.data.QueryProjectProfitListResponse.ProfitItem;
import com.travel.server.manager.dto.response.project.data.QueryProjectProfitListResponse.ProjectProfitItem;
import com.travel.server.manager.impl.command.AbstractCommand;
import com.travel.server.manager.impl.dal.OrderDal;
import com.travel.server.manager.impl.dal.SpecialDal;
import com.travel.server.manager.model.dto.data.SpecialOrderDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Author: LiZhenhui
 * @Date: 2018/11/29 12:11
 * @Desc:
 */
@Component
@Slf4j
public class QueryProjectProfitListCommand extends AbstractCommand<QueryProjectProfitListRequest, QueryProjectProfitListResponse> {

    @Autowired
    private QueryProjectCostCommand queryProjectCostCommand;

    @Autowired
    private OrderDal orderDal;

    @Autowired
    private SpecialDal specialDal;

    @Override
    protected void checkInput(QueryProjectProfitListRequest request) {

    }

    @Override
    public QueryProjectProfitListResponse handle(QueryProjectProfitListRequest request) {
        QueryProjectProfitListResponse response = new QueryProjectProfitListResponse();

        Date startTime = DateUtil.getDataTime(request.getStartTime());
        Date endTime = DateUtil.getDataEndTime(request.getEndTime());
        List<ProjectProfitItem> projectProfitList = queryProjectProfitItem(startTime, endTime, request.getPage(), request.getLimit());
        if(CommonConstant.YES.equals(request.getIsCount())){
            Date today = DateUtil.get(new Date(), 0, 0, 0, 0);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(today);
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            Date yesterday = DateUtil.get(calendar.getTime(), 23, 59, 59, 999);
            List<ProjectProfitItem> countList = queryProjectProfitItem(today, yesterday, null, null);
            if(!CollectionUtil.isEmpty(countList)){
                for(ProjectProfitItem item : countList){
                    if(DateUtil.isSameDay(item.getTravelDate(), today)){
                        response.setToday(item.getProfit());
                    }else if(DateUtil.isSameDay(item.getTravelDate(), yesterday)){
                        response.setYesterday(item.getProfit());
                    }
                }
            }
        }else{
            response.setToday(null);
            response.setYesterday(null);
        }

        int totalNum = specialDal.selectSpecialCount(startTime, endTime);
        response.setTotalNum(totalNum);

        response.setProfitList(makeProfitList(startTime, endTime));

        response.setProjectProfitList(projectProfitList);
        return response;
    }

    private List<ProfitItem> makeProfitList(Date startTime, Date endTime){
        List<ProfitItem> profitList = new ArrayList<>();
        Calendar weekCalendar = Calendar.getInstance();
        weekCalendar.setTime(startTime);
        weekCalendar.add(Calendar.DATE, -7);
        Date weekStartTime = weekCalendar.getTime();
        List<ProjectProfitItem> list = queryProjectProfitItem(weekStartTime, endTime, null, null);
        Map<String, String> map = makeProjectProfitMap(list);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startTime);
        while(calendar.getTime().before(endTime) || calendar.getTime().equals(endTime)){
            String key = DateUtil.YYYYMMDD.format(calendar.getTime());
            String profit = map.get(key);
            Calendar lastWeek = Calendar.getInstance();
            lastWeek.setTime(calendar.getTime());
            lastWeek.add(Calendar.DATE, -7);
            String lastWeekKey = DateUtil.YYYYMMDD.format(lastWeek.getTime());
            String lasWeekProfit = map.get(lastWeekKey);
            ProfitItem item = new ProfitItem();
            BigDecimal profitDecimal = new BigDecimal("0");
            if(StringUtils.isBlank(profit)){
                item.setProfit("0");
            }else{
                profitDecimal = new BigDecimal(profit);
                item.setProfit(profit);
            }
            BigDecimal lastWeekProfitDecimal = new BigDecimal("0");
            if(StringUtils.isNotBlank(lasWeekProfit)){
                lastWeekProfitDecimal = new BigDecimal(lasWeekProfit);
            }
            item.setAdd(CommonUtil.getProportion(profitDecimal.subtract(lastWeekProfitDecimal), lastWeekProfitDecimal));
            item.setDate(calendar.getTime());
            item.setWeekDate(lastWeek.getTime());
            profitList.add(item);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
        }
        return profitList;
    }

    private Map<String, String> makeProjectProfitMap(List<ProjectProfitItem> list){
        Map<String, String> map = new HashMap<>();
        for(ProjectProfitItem item : list){
            map.put(DateUtil.YYYYMMDD.format(item.getTravelDate()), item.getProfit());
        }
        return map;
    }

    public List<ProjectProfitItem> queryProjectProfitItem(Date startTime, Date endTime, Integer page, Integer limit){
        List<ProjectProfitItem> profitList = new ArrayList<>();
        QueryProjectCostRequest queryProjectCostRequest = new QueryProjectCostRequest();
        queryProjectCostRequest.setStartTime(DateUtil.YYYY_MM_DD.format(startTime));
        queryProjectCostRequest.setEndTime(DateUtil.YYYY_MM_DD.format(endTime));
        queryProjectCostRequest.setIsCount(CommonConstant.NO);
        queryProjectCostRequest.setPage(page);
        queryProjectCostRequest.setLimit(limit);
        QueryProjectCostResponse queryProjectCostResponse = queryProjectCostCommand.handle(queryProjectCostRequest);
        List<CostItem> costList = queryProjectCostResponse.getCostList();
        if(!CollectionUtil.isEmpty(costList)){
            List<SpecialOrderDto> specialOrderList = orderDal.selectSpecialOrder(startTime, endTime);
            Map<Integer, Integer> orderMap = makeOrder(specialOrderList, 1);
            Map<Integer, Integer> refundMap = makeOrder(specialOrderList, 2);
            for(CostItem costItem : costList){
                ProjectProfitItem item = new ProjectProfitItem();
                item.setCost(costItem.getCost());
                Integer order = orderMap.get(costItem.getId());
                if(order == null){
                   order = 0;
                }
                Integer refund = refundMap.get(costItem.getId());
                if(refund == null){
                    refund = 0;
                }
                order = order + refund;
                item.setOrder(order + "");
                item.setRefund(refund + "");
                item.setProject(costItem.getProject());
                item.setTravelDate(costItem.getTravelDate());
                String projectAmount = costItem.getProjectAmount();
                String applyAmount = costItem.getApplyAmount();
                String cost = item.getCost();
                BigDecimal profit = new BigDecimal("0");
                if(StringUtils.isNotBlank(projectAmount)){
                    profit = profit.add(new BigDecimal(projectAmount));
                }
                if(StringUtils.isNotBlank(applyAmount)){
                    profit = profit.add(new BigDecimal(applyAmount));
                }
                if(StringUtils.isNotBlank(cost)){
                    profit = profit.subtract(new BigDecimal(cost));
                }
                item.setProfit(profit.toString());
                profitList.add(item);
            }
        }
        return profitList;
    }

    private Map<Integer, Integer> makeOrder(List<SpecialOrderDto> list, Integer type){
        Map<Integer, Integer> map = new HashMap<>();
        if(1 == type){
            for(SpecialOrderDto dto : list){
                map.put(dto.getId(), dto.getOrderCount());
            }
        }else if(2 == type){
            for(SpecialOrderDto dto : list){
                map.put(dto.getId(), dto.getRefundCount());
            }
        }
        return map;
    }
}
